    var folderLists = {};  
    var smartFolderLists = null;

function handleFolderTree(parentFolder){    
    if (!parentFolder) return;    
    if (parentFolder.children) {          
        _.each(parentFolder.children, function(node){
            node.parent = parentFolder;               
            handleFolderTree(node);
        });
    }
}   

    var _curFolder = window.rootFolder;   
    var _sortList = {
        "name": {
            "asc": function(a, b) {   
                if (a.type === 'cmis:folder' && a.type !== b.type) {
                    return -1;
                }
                if (b.type === 'cmis:folder' && a.type !== b.type) {
                    return 1;
                }
                if (a.name == b.name){
                    return 0;
                }
                else{
                    return a.name > b.name ? 1 : -1;   
                }
            },
            "desc": function(a, b) {   
                if (a.type === 'cmis:folder' && a.type !== b.type) {
                    return -1;
                }
                if (b.type === 'cmis:folder' && a.type !== b.type) {
                    return 1;
                }            
                if (a.name == b.name){
                    return 0;
                }
                else{
                   return a.name > b.name ? -1 : 1;   
                }
            }
        },
        "time": {
            "asc": function(a, b) {  
                if (a.type === 'cmis:folder' && a.type !== b.type) {
                    return -1;
                }
                if (b.type === 'cmis:folder' && a.type !== b.type) {
                    return 1;
                }
                var a_time = Date.parse(a.time)/1000;
                var b_time = Date.parse(b.time)/1000;
                if (a_time == b_time){
                    return 0;
                }       
                else{
                    return (a_time > b_time)? 1 : -1;
                }               
            },
            "desc": function(a, b) {    
                if (a.type === 'cmis:folder' && a.type !== b.type) {
                    return -1;
                }
                if (b.type === 'cmis:folder' && a.type !== b.type) {
                    return 1;
                }
                var a_time = Date.parse(a.time)/1000;
                var b_time = Date.parse(b.time)/1000;
                if (a_time == b_time){
                    return 0;
                }       
                else{
                    return (a_time > b_time)? -1 : 1;
                }        
            }
        }
    };

    function sort_folder_first(a, b) {
        if (a.type === 'cmis:folder' && a.type !== b.type) {
            return -1;
        }
        if (b.type === 'cmis:folder' && a.type !== b.type) {
            return 1;
        }
        return 0;
    }  

    function addObj2List(folder, obj) {
        var folderList = folderLists[folder.id];
        if (folderList){
            obj.parent = folder;
            if (obj.type == "cmis:folder"){
                var pos = 0;
                _.every(folderList.data, function(node, index){                   
                    if (node.type == "cmis:folder"){     
                        pos = index;                   
                        return true;
                    }
                    return false;
                })
                folderList.data.splice(pos+1, 0, obj);
            }
            else{
                folderList.data.push(obj);        
            }       
        }
    }   
    
    function removeObjFromList(folder, obj){
        if (!folder) return;
        var folderList = folderLists[folder.id];
        if (folderList){
           folderList.data = removeInArray(folderList.data, obj); 
        }
    }    

    function removeInArray(aArray, item){
        return _.reject(aArray, function(_item){
            return _item.id == item.id;
        });
    }
    function removeFolderInChildren(parentFolder, folder){
        if (parentFolder.children) {
            _.every(parentFolder.children, function(node){
                if (node.id === folder.id){
                    parentFolder.children = removeInArray(parentFolder.children, folder);
                    removeObjFromList(parentFolder, folder);                  
                    return false;
                }
                return true;
               // else{
                //    return removeFolderInChildren(node, folder);                  
               // }              
            });
        }
        return true;
    }

function findFolderInChildren(parentFolder, folderId){        
    var ret = null;
    if (parentFolder.children) {
        _.every(parentFolder.children, function(node){
            if (node.id === folderId){
               ret = node;
               return false;
            }
            else{
               ret = findFolderInChildren(node, folderId);                  
               return !ret;
            }              
        });
    }
    return ret;
}

export default {  
    selectedObjects: [],
    setRootFolder: function(rootFolder){    
        handleFolderTree(rootFolder);
        rootFolder.name = i18n.t("My archives");    
    },
    getFolderTree: function(){
        return $.when(window.rootFolder);
    },   
    getFolderChildren: function(folder){
        var _this = this;
        var folderId = folder.id;
        /*if (folderLists[folderId]){
            return $.when(folderLists[folderId]);
        }*/
        var promise = CMISService.getFolderChildren(folder.id)
            .done(function(data) {
                _.each(data.data, function(item) {
                    item.parent = folder;
                });
                data.data.sort(sort_folder_first);
                folderLists[folderId] = data;
                return folderLists[folderId];
            })
            .fail(function(data) {
                delete folderLists[folderId]; //delete promise
            })
        return promise;
    },
    getBrotherFolder: function(object) {      
        var parentFolder = object.parent;
        if (!parentFolder) return [];
        var folderList  = folderLists[parentFolder.id];
        if (!folderList) return [];
        return _.filter(folderList.data, function(node){
            return (node.type == 'cmis:folder' && node.id !== object.id);
        });   
    },
    getFolderPath: function(folder) {
        var path = [];          
        path.push(folder);
        var parent = folder.parent;
        while(parent){
            path.push(parent);
            parent = parent.parent;
        }
        return path;
    },
    getFolderById: function(folderId) {
        if (window.rootFolder.id == folderId){
            return window.rootFolder;
        }
        return findFolderInChildren(window.rootFolder, folderId);
    },
    isContainIn : function(contained, container){
        if (container.type !== "cmis:folder"){
            return false;
        }
        var parentFolder = this.getFolderById(container.id);
        return !!findFolderInChildren(parentFolder, contained.id);
    },
    getFolderContainDocument : function(doc){
        var bFind = false;
        var ret;
        _.every(folderLists, function(folderList){           
            _.every(folderList.data, function(_doc){
                if (_doc.id == doc.id){                    
                    bFind = true;
                    return false;
                }
                return true;
            });
            if (bFind){
                ret = folderList.id;
                return false;
            }         
            return true;
        });

        if (bFind){
            return this.getFolderById(ret);
        }
        return null;
    },
    removeFolder: function(folder) {
        var _this = this;
        return CMISService.removeFolder(folder)
            .done(function(response) {
                removeFolderInChildren(folder.parent, folder);
                _this.folderTreeChanged();
                if (_curFolder.id === folder.id) {
                    _this.setCurFolder(_curFolder.parent);
                }
                if (_curFolder.id === folder.parent.id) {
                    _this.folderListChanged({
                        action: 'FOLDER_LIST_REMOVE',
                        items: [folder]
                    });
                }
                return response;
            });
    },    
    addFolder: function(parentId, folder){
        var parentFolder = this.getFolderById(parentId);
        folder.parent = parentFolder;
        if (!parentFolder.children){
            parentFolder.children = [];
        }
        parentFolder.children.push(folder);     
        addObj2List(parentFolder, folder);  
        this.folderTreeChanged();  
        if (_curFolder.id == parentId){
            this.folderListChanged({
                action: 'FOLDER_LIST_ADD',
                items: [folder]
            });
        }       
    },
    addDocument: function(folder, doc){       
        addObj2List(folder, doc);          
        if (_curFolder.id == folder.id){
            this.folderListChanged({
                action: 'FOLDER_LIST_ADD',
                items: [doc]
            });
        }     
    },  
    sort: function(data, orderOption){   
        if (!_.isArray(data)) return; 
        var sorter = this.getSorter(orderOption.orderBy, orderOption.order);       
        if (sorter) {          
            data.sort(sorter);
        }       
    },
    getSorter: function(orderBy, order){
        if (_sortList[orderBy]){
            if (order){
                return _sortList[orderBy].asc;
            }
            else{
                return _sortList[orderBy].desc;
            }                     
        }
        return null;
    },    
    removeDocument: function(doc){
        var _this = this;    
        var folder = doc.parent;
        if (!folder){
           folder = this.getFolderContainDocument(doc);
        }
        return CMISService.removeDocument(doc)
            .done(function(response){
                if (folder) {
                    removeObjFromList(folder, doc);
                    if (_curFolder.id == folder.id) {
                        _this.folderListChanged({
                            action: 'FOLDER_LIST_REMOVE',
                            items: [doc]
                        });
                    }
                }
                _this.documentRemoved(doc);                
                return response;
            })            
    },
    getCurFolder: function() {       
        return _curFolder;
    },   
    copyTo: function(document, targetFolder){
        var _this = this;
        var dtd = $.Deferred();            
        CMISService.copyTo(document, targetFolder)
        .done(function(response){
            dtd.resolve(response);
                if (_curFolder.id == targetFolder.id) {
                    _this.folderListChanged({
                        action: 'FOLDER_LIST_ADD',
                        items: [response.data]
                    });
                }
        })
        .fail(function(response){
            dtd.reject(response);
        });
        return dtd.promise(); 
    },
    moveTo: function(obj, sourceFolderId, targetFolderId){
        var _this = this;       
        var sourceFolder = this.getFolderById(sourceFolderId);
        var targetFolder = this.getFolderById(targetFolderId);
        return CMISService.moveTo(obj, sourceFolder, targetFolder)
            .done(function(response){       
                if (obj.type == 'cmis:folder') {                                
                    _this.addFolder(targetFolder.id, response.data);
                    removeFolderInChildren(sourceFolder, obj);                   
                } else {
                    removeObjFromList(sourceFolder, obj);
                    addObj2List(targetFolder, obj);
                }

                if (_curFolder.id == targetFolder.id) {
                    _this.folderListChanged({
                        action: 'FOLDER_LIST_ADD',
                        items: [response.data]
                    });
                }
                if (_curFolder.id == sourceFolder.id) {
                    _this.folderListChanged({
                        action: 'FOLDER_LIST_REMOVE',
                        items: [obj]
                    });
                }

                if (obj.type == "cmis:folder"){
                    _this.folderTreeChanged();
                }
                return response;
            })               
    },
    filingDocument: function(docs){
        var _this = this;       
        return CMISService.filingDocument(docs)
            .done(function(response) {       
                _this.propertiesChanged(_this.selectedObjects[0]);             
                return response;
            })           
            .always(function(){
                 _.each(docs, function(doc){
                    _.each(doc.path, function(folder){
                        delete folderLists[folder.id];
                    });
                });   
            })  
    },
    unfillDocument : function(doc, targetFolderId){       
        var _this = this;      
        return CMISService.unfillDocument(doc.id, targetFolderId)
            .done(function(response) { 
                removeObjFromList({id: targetFolderId}, doc);    
                if (_curFolder.id == targetFolderId){
                    _this.folderListChanged({
                        action: 'FOLDER_LIST_REMOVE',
                        items: [doc]
                    });                     
                }
                _this.propertiesChanged(doc);     
                _this.documentRemoved(doc);                
                return response;    
            })  
    },
    updateProperties :function(object, propName, newValue, oldValue) {
        var _this = this;       
        return CMISService.updateProperties(object, propName, newValue)
            .done(function(response){             
                if (object.type == "cmis:folder"){
                    var folder = _this.getFolderById(object.id);
                    if (propName == "cmis:name"){
                        folder.name = newValue;
                    }
                   _this.folderTreeChanged();     
                }
                _this.folderListChanged({
                    action: 'FOLDER_LIST_ADD',
                    items: [object]
                });
                _this.propertiesChanged(object);
                return response;
            })
            .fail(function(response){
                object.name = oldValue;               
                _this.folderListChanged({
                    action: 'FOLDER_LIST_ADD',
                    items: [object]
                });
                _this.propertiesChanged(object);
                return response;
            });       
    },
    setCurFolder: function(folder, force){     
        if (_curFolder && folder && folder.id === _curFolder.id && !force) return;     
        var _this = this;
        _curFolder = folder;       
        this.curFolderChanged(folder);      
        CMISService.getMyPermission([folder.id]).done(function(response){         
            _this.permissonChanged(response[folder.id]);
        });
    },
    getMyPermission:function(folderIds){        
        return CMISService.getMyPermission(folderIds);            
    },
    getSelectedObject: function(){
        return this.selectedObjects;
    },
    setSelectedObject: function(folderOrDoc){     
        if (!folderOrDoc){
            this.selectedObjects = [];
            this.selectedObjectChanged(this.selectedObjects);
            return;
        }
        if (this.selectedObjects.length == 1 && _.contains(this.selectedObjects, folderOrDoc)){
            return;
        }       
        this.selectedObjects = [folderOrDoc];
        this.selectedObjectChanged(this.selectedObjects);
    },      
    triggerSelectedObject: function(folderOrDoc) {
        if (_.contains(this.selectedObjects, folderOrDoc)) {
            this.selectedObjects = _.reject(this.selectedObjects, function(node) {
                return node === folderOrDoc;
            })
        } else {
            this.selectedObjects.push(folderOrDoc);
        }      
        this.selectedObjectChanged(this.selectedObjects);
    },
    rename: function(folderOrDoc){
        this.renameAction(folderOrDoc);
    },
    getSmartFolderList: function(){
        if (smartFolderLists){          
            return $.when(smartFolderLists);
        }
        var promise = CMISService.getSmartFolderList()
            .done(function(response){
                smartFolderLists = response;       
                return smartFolderLists;                     
            })
            .fail(function(response){
                smartFolderLists = null;          
                return response;
            });

        smartFolderLists = promise;
        return promise;
    },
    createSmartFolder : function(requestData) {
        var _this = this;
        return CMISService.createSmartFolder(requestData)
            .done(function(response){
                smartFolderLists.push(requestData);
                _this.smartFolderListChanged();
                return response;
            });   

        
    },
    removeSmartFolder : function(smartFolder){
        var _this = this;
        return CMISService.removeSmartFolder(smartFolder)
            .done(function(response){
                smartFolderLists = _.reject(smartFolderLists, function(node){
                   return node.title == smartFolder.title;
                });     
                _this.smartFolderListChanged();
                return response;
            })
            .fail(function(response){
                smartFolderLists = null;
                return response;
            });
    },
    smartFolderListChanged : function(callback, on){
        this.someChanged('smartFolderListChanged_event', callback, on); 
    },   
    propertiesChanged: function(callback, on){
        this.someChanged('propertiesChanged_event', callback, on); 
    },
    documentRemoved: function(callback, on){
        this.someChanged('documentRemoved_event', callback, on); 
    },
    versionListChanged: function(callback, on) {
        this.someChanged('versionListChanged_event', callback, on); 
    },
    folderListChanged: function(callback, on) {  
        this.someChanged('folderListChanged_event', callback, on); 
    },
    curFolderChanged: function(callback, on){          
        this.someChanged('curFolderChanged_event', callback, on);  
    },   
    permissonChanged: function(callback, on){
         this.someChanged('permissonChanged_event', callback, on);  
    },
    selectedObjectChanged: function(callback, on){
        this.someChanged('selectedObjectChanged_event', callback, on);
    },   
    folderTreeChanged: function(callback, on) {
        this.someChanged('folderTreeChanged_event', callback, on);
    },    
    renameAction : function(callback, on){
        this.someChanged('renameAction_event', callback, on);   
    },
    someChanged: function(eventName, callback, on){
        if (typeof callback == "function") {
            if (typeof on == 'undefined' || on){    
                $(this).on(eventName, callback);
            }
            else{
                $(this).off(eventName, callback);
            }
        } else {
            $(this).trigger(eventName, [callback]);
        }
    }
  }; 


